﻿/*========================== 
 * @author 郑金泉
 * @desc 数据读取类
 * ========================= */
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

using Obsidian.Edm;

namespace Obsidian.Data.Sql
{
    public class DataReader
    {
        private IDataReader dataReader = null;

        private bool autoClose = true;

        /// <summary>
        /// 读取完第一个结果集是否自动关闭
        /// </summary>
        public bool AutoClose
        {
            get { return autoClose; }
            set { autoClose = value; }
        }

        public DataReader(IDataReader dataReader)
        {
            this.dataReader = dataReader;
        }

        /// <summary>
        /// 使读取器前进到下一行记录
        /// </summary>
        /// <returns></returns>
        public bool Read()
        {
            if (dataReader.Read())
            {
                return true;
            }
            else
            {
                if (autoClose)
                    dataReader.Close();
                return false;
            }
        }

        public void ReadTo(params IModel[] models)
        {
            int count = dataReader.FieldCount;
            for (var i = 0; i < count; i++)
            {
                IModelField field = GetField(dataReader.GetName(i), models);
                if (field != null)
                {
                    object ov = dataReader.GetValue(i);
                    if (!Convert.IsDBNull(ov))
                    {
                        field.Set(ov);
                    }
                }
            }
        }

        public void ReadTo<T>(EntityField<T> field) where T : IModel, new()
        {
            if (field.IsNull)
            {
                T o = new T();
                this.ReadTo(o);
                field.Set(o);
            }
            else
            {
                this.ReadTo(field.Value);
            }
        }


        private IModelField GetField(string prefixAsName, params IModel[] models)
        {
            IModelField field;
            foreach (IModel m in models)
            {
                field = m.GetFieldByQueryAlias(prefixAsName);
                if (field != null)
                    return field;
            }
            return null;
        }
        
        /// <summary>
        /// 仅读取第一笔数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T ReadFirst<T>() where T : IModel, new()
        {
            return this.ReadFirst<T>(true);
        }

        /// <summary>
        /// 仅读取第一笔数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T ReadFirst<T>(bool closeReader) where T: IModel, new()
        {
            if (this.Read())
            {
                T m = new T();
                this.ReadTo(m);
                if (closeReader)
                    this.Close();
                return m;
            }
            else
            {
                this.Close();
                return default(T);
            }
        }

        /// <summary>
        /// 读取列表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public List<T> ReadList<T>() where T : IModel, new()
        {
            List<T> list = new List<T>();
            while (this.Read())
            {
                T t = new T();
                ReadTo(t);
                list.Add(t);
            }
            this.Close();
            return list;
        }

        public List<IModel> ReadList(ModelGene mg)
        {
            List<IModel> list = new List<IModel>();
            while (this.Read())
            {
                IModel o = (IModel)mg.CreateModel();
                ReadTo(o);
                list.Add(o);
            }
            this.Close();
            return list;
        }

        /// <summary>
        /// 关闭读取器
        /// </summary>
        public void Close()
        {
            dataReader.Close();
        }

        #region GetValue

        /// <summary>
        /// 获得指定字段的值
        /// </summary>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public object GetValue(string fieldName)
        {
            object obj = GetCurrentDataReaderValue(fieldName);
            return obj;
        }

        /// <summary>
        /// 获得指定字段的值
        /// </summary>
        /// <param name="field">字段</param>
        /// <returns>值</returns>
        public object GetValue(IModelField field)
        {
            object obj = GetCurrentDataReaderValue(field);
            return obj;
        }

        /// <summary>
        /// 获得指定字段的值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="whenNullValue">当结果为空时的值</param>
        /// <returns>值</returns>
        /// <summary>
        public object GetValue(IModelField field, object whenNullValue)
        {
            object obj = GetCurrentDataReaderValue(field);
            return obj == Convert.DBNull ? whenNullValue : obj;
        }

        #endregion

        #region GetInt32

        /// <summary>
        ///  获得指定字段的值
        /// </summary>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public int GetInt32(string fieldName)
        {
            object obj = GetCurrentDataReaderValue(fieldName);
            return Convert.ToInt32(obj);
        }

        /// <summary>
        /// 获得指定字段的值
        /// </summary>
        /// <param name="field">字段</param>
        /// <returns>值</returns>
        public int GetInt32(IModelField field)
        {
            object obj = GetCurrentDataReaderValue(field);
            return Convert.ToInt32(obj);
        }

        /// <summary>
        /// 获得指定字段的值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="whenNullValue">当结果为空时的值</param>
        /// <returns>值</returns>
        /// <summary>
        public int GetInt32(IModelField field, int whenNullValue)
        {
            object obj = GetCurrentDataReaderValue(field);
            return obj == Convert.DBNull ? whenNullValue : Convert.ToInt32(obj);
        }

        #endregion

        #region GetInt64

        /// <summary>
        /// 获得指定字段的值
        /// </summary>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public long GetInt64(string fieldName)
        {
            object obj = GetCurrentDataReaderValue(fieldName);
            return Convert.ToInt64(obj);
        }

        /// <summary>
        /// 获得指定字段的值
        /// </summary>
        /// <param name="field">字段</param>
        /// <returns>值</returns>
        public long GetInt64(IModelField field)
        {
            object obj = GetCurrentDataReaderValue(field);
            return Convert.ToInt64(obj);
        }

        /// <summary>
        /// 获得指定字段的值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="whenNullValue">当结果为空时的值</param>
        /// <returns>值</returns>
        /// <summary>
        public long GetInt64(IModelField field, long whenNullValue)
        {
            object obj = GetCurrentDataReaderValue(field);
            return obj == Convert.DBNull ? whenNullValue : Convert.ToInt64(obj);
        }

        #endregion

        #region GetString

        /// <summary>
        /// 获得指定字段的值
        /// </summary>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public string GetString(string fieldName)
        {
            object obj = GetCurrentDataReaderValue(fieldName);
            return Convert.ToString(obj);
        }

        /// <summary>
        /// 获得指定字段的值
        /// </summary>
        /// <param name="field">字段</param>
        /// <returns>值</returns>
        public string GetString(IModelField field)
        {
            object obj = GetCurrentDataReaderValue(field);
            return Convert.ToString(obj);
        }

        /// <summary>
        /// 获得指定字段的值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="whenNullValue">当结果为空时的值</param>
        /// <returns>值</returns>
        /// <summary>
        public string GetString(IModelField field, string whenNullValue)
        {
            object obj = GetCurrentDataReaderValue(field);
            return obj == Convert.DBNull ? whenNullValue : Convert.ToString(obj);
        }

        #endregion

        #region GetDecimal

        public decimal GetDecimal(string fieldName)
        {
            object obj = GetCurrentDataReaderValue(fieldName);
            return Convert.ToDecimal(obj);
        }

        /// <summary>
        /// 获得指定字段的值
        /// </summary>
        /// <param name="field">字段</param>
        /// <returns>值</returns>
        public decimal GetDecimal(IModelField field)
        {
            object obj = GetCurrentDataReaderValue(field);
            return Convert.ToDecimal(obj);
        }

        /// <summary>
        /// 获得指定字段的值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="whenNullValue">当结果为空时的值</param>
        /// <returns>值</returns>
        /// <summary>
        public decimal GetDecimal(IModelField field, decimal whenNullValue)
        {
            object obj = GetCurrentDataReaderValue(field);
            return obj == Convert.DBNull ? whenNullValue : Convert.ToDecimal(obj);
        }

        #endregion

        #region GetBoolean

        /// <summary>
        /// 获得指定字段的值
        /// </summary>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public bool GetBoolean(string fieldName)
        {
            object obj = GetCurrentDataReaderValue(fieldName);
            return Convert.ToBoolean(obj);
        }

        /// <summary>
        /// 获得指定字段的值
        /// </summary>
        /// <param name="field">字段</param>
        /// <returns>值</returns>
        public bool GetBoolean(IModelField field)
        {
            object obj = GetCurrentDataReaderValue(field);
            return Convert.ToBoolean(obj);
        }

        /// <summary>
        /// 获得指定字段的值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="whenNullValue">当结果为空时的值</param>
        /// <returns>值</returns>
        /// <summary>
        public bool GetBoolean(IModelField field, bool whenNullValue)
        {
            object obj = GetCurrentDataReaderValue(field);
            return obj == Convert.DBNull ? whenNullValue : Convert.ToBoolean(obj);
        }

        #endregion

        #region GetDateTime

        /// <summary>
        /// 获得指定字段的值
        /// </summary>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public DateTime GetDateTime(string fieldName)
        {
            object obj = GetCurrentDataReaderValue(fieldName);
            return Convert.ToDateTime(obj);
        }

        /// <summary>
        /// 获得指定字段的值
        /// </summary>
        /// <param name="field">字段</param>
        /// <returns>值</returns>
        public DateTime GetDateTime(IModelField field)
        {
            object obj = GetCurrentDataReaderValue(field);
            return Convert.ToDateTime(obj);
        }

        /// <summary>
        /// 获得指定字段的值
        /// </summary>
        /// <param name="field">字段</param>
        /// <param name="whenNullValue">当结果为空时的值</param>
        /// <returns>值</returns>
        /// <summary>
        public DateTime GetDateTime(IModelField field, DateTime whenNullValue)
        {
            object obj = GetCurrentDataReaderValue(field);
            return obj == Convert.DBNull ? whenNullValue : Convert.ToDateTime(obj);
        }

        #endregion

        /// <summary>
        /// 获得读取器当前行指定字段的值
        /// </summary>
        /// <param name="field">字段</param>
        /// <returns>值</returns>
        private object GetCurrentDataReaderValue(IModelField field)
        {
            return GetCurrentDataReaderValue(field.GetDbField().QueryAlias);
        }

        private object GetCurrentDataReaderValue(string fieldName)
        {
            object obj = dataReader[fieldName];
            return obj;
        }
    }
}
